package com.sihan.framework.etm.service.business.impl;

import com.framework.exception.BusinessException;
import com.framework.model.ApiResult;
import com.framework.model.PageResult;
import com.framework.mybatis.Condition;
import com.framework.util.PageUtils;
import com.github.pagehelper.PageHelper;
import com.sihan.framework.etm.common.CacheOperatorInfo;
import com.sihan.framework.etm.common.CommonBiz;
import com.sihan.framework.etm.common.util.DateUtils;
import com.sihan.framework.etm.common.util.EtmWebUtil;
import com.sihan.framework.etm.dto.business.BaseDTO;
import com.sihan.framework.etm.dto.business.ExceptionToolAddDTO;
import com.sihan.framework.etm.dto.business.ToolOverviewDTO;
import com.sihan.framework.etm.entity.DeviceSurplusTool;
import com.sihan.framework.etm.entity.business.ToolCheckModel;
import com.sihan.framework.etm.entity.business.ToolInspectDetail;
import com.sihan.framework.etm.entity.business.ToolInspectInDetail;
import com.sihan.framework.etm.entity.business.ToolInspectInMaster;
import com.sihan.framework.etm.entity.business.ToolInspectMaster;
import com.sihan.framework.etm.enums.CacheKeyName;
import com.sihan.framework.etm.enums.MqttSendCommandFunc;
import com.sihan.framework.etm.enums.OperateType;
import com.sihan.framework.etm.mapper.CommonMapper;
import com.sihan.framework.etm.mapper.baseData.CheckDateScheduleMapper;
import com.sihan.framework.etm.mapper.baseData.ToolMapper;
import com.sihan.framework.etm.mapper.business.InspectDetailMapper;
import com.sihan.framework.etm.mapper.business.InspectInDetailMapper;
import com.sihan.framework.etm.mapper.business.InspectInMasterMapper;
import com.sihan.framework.etm.mapper.business.InspectMasterMapper;
import com.sihan.framework.etm.mapper.business.ToolCheckRecordMapper;
import com.sihan.framework.etm.service.business.CheckService;
import com.sihan.framework.etm.vo.business.BaseToolInfo;
import com.sihan.framework.etm.vo.business.BorrowPlanVO;
import com.sihan.framework.etm.vo.business.ToolOverviewVO;
import lombok.RequiredArgsConstructor;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author gyz
 * @version 1.0
 * @since jdk1.8
 */
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CheckServiceImpl implements CheckService {

	private final InspectDetailMapper checkMapper;
	
	private final CommonBiz commonBiz;
	
	private final InspectMasterMapper inspectMasterMapper;
	
	private final InspectInMasterMapper inspectInMasterMapper;
	
	private final InspectInDetailMapper inspectInDetailMapper;
	
	private final ToolCheckRecordMapper toolCheckRecordMapper;
	
	private final ToolMapper toolMapper;
	
	private final InspectDetailMapper inspectDetailMapper;
	
	private final CommonMapper commonMapper;
	
	private final CheckDateScheduleMapper checkDateScheduleMapper;
	
	public static final Object lock = new Object();

	@Override
	public PageResult<ToolOverviewVO> getToolList(ToolOverviewDTO dto) {
		if(!StringUtils.isBlank(dto.getCheckStartDate())) {
			dto.setCheckStartDate(dto.getCheckStartDate() + " 00:00:00:000");
		}
		if(!StringUtils.isBlank(dto.getCheckEndDate())) {
			dto.setCheckEndDate(dto.getCheckEndDate() + " 23:59:59:999");
		}
		PageHelper.startPage(dto);
		List<ToolOverviewVO> toolOverviews = checkMapper.getToolList(dto);
		if(null != toolOverviews && !toolOverviews.isEmpty()) {
			toolOverviews.stream().forEach(vo->{
				vo.setExpiredDate(StringUtils.isBlank(vo.getExpiredDate())?"":vo.getExpiredDate().substring(0, 10));
			});
		}
		return PageUtils.toPageResult(toolOverviews);
	}

	@Override
	public PageResult<ToolOverviewVO> getToolCheckList(ToolOverviewDTO dto) {
		if(!StringUtils.isBlank(dto.getCheckStartDate())) {
			dto.setCheckStartDate(dto.getCheckStartDate() + " 00:00:00:000");
		}
		if(!StringUtils.isBlank(dto.getCheckEndDate())) {
			dto.setCheckEndDate(dto.getCheckEndDate() + " 23:59:59:999");
		}
		PageHelper.startPage(dto);
		List<ToolOverviewVO> toolOverviews = checkMapper.getToolCheckList(dto);
		if(null != toolOverviews && !toolOverviews.isEmpty()) {
			toolOverviews.stream().forEach(vo->{
				vo.setLastInspectionDate(StringUtils.isBlank(vo.getLastInspectionDate())?"":vo.getLastInspectionDate().substring(0, 10));
				if(vo.getHasReport() == 1) {
					//vo.setReportAddr(masterConfig.getReportAddr()+"/"+vo.getTid()+"/"+vo.getInspectBatch());
				}
				vo.setInspectResult(vo.getInspectResult().equals("1")?"合格":"不合格");
			});
		}
		return PageUtils.toPageResult(toolOverviews);
	}

	@Override
	public void updateRemindCycle(String remindCycle) {
		if(StringUtils.isBlank(remindCycle)) {
			throw new BusinessException("请输入需要提前提醒的天数");
		}
		if(Integer.parseInt(remindCycle) < 0 || Integer.parseInt(remindCycle) > 9999) {
			throw new BusinessException("请输入正确的天数");
		}
		int updateRemindCycleLog = checkMapper.updateRemindCycle(remindCycle);
		if(updateRemindCycleLog != 1){
			throw new BusinessException("参数错误！");
		}else {
			//生成检验提醒记录
			List<BaseToolInfo> baseToolInfos = checkDateScheduleMapper.getNeedCheckTools();
			if(null != baseToolInfos && !baseToolInfos.isEmpty()) {
				if(checkDateScheduleMapper.checkTodayHasInspectRemind() <= 0) {
					checkDateScheduleMapper.addInspectRemindMaster();
				}
				String masterId = checkDateScheduleMapper.getLatestMasterId();
				baseToolInfos.stream().forEach(info->{
					info.setMasterId(masterId);
					checkDateScheduleMapper.addInspectRemindDetail(info);
				});
			}
		}
	}

	@Override
	public List<BorrowPlanVO> getCheckToolOutStatistical() {
		String masterId = null;
		//synchronized (lock) {
			String userId = commonBiz.checkValidatedUserId();
			masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
			if(StringUtils.isBlank(userId)) {
				masterId = this.checkInspectMasterId(userId, masterId);
			}
		//}
		List<BorrowPlanVO> checkToolStatistical = checkMapper.getCheckToolOutStatistical(masterId);
		return checkToolStatistical;
	}
	
	/**
	 * 
	 * @description  检验是否有出库的主表
	 * @param userId
	 * @param masterId
	 * @return
	 * @auther 韩兵
	 * @Date 2020年8月2日
	 * @return Long
	 */
	private String checkInspectMasterId(String userId,String masterId) {
		ToolInspectMaster master = null;
		if(StringUtils.isBlank(masterId)) {
			master = new ToolInspectMaster();
			master.setCreateTime(new Date());
			master.setStatus(0);
			master.setUserId(userId);
			inspectMasterMapper.insert(master);
			masterId = master.getId();
			CacheOperatorInfo.setMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), masterId);
			CacheOperatorInfo.setMapValue(CacheKeyName.BUSINESS_OPERATE_TYPE.getValue(), OperateType.INSPECT_OUT_WAREHOUSE.getValue());
		}
		return masterId;
	}

	@Override
	public PageResult<BaseToolInfo> getToolCheckOutList(BaseDTO dto) {
		String masterId = null;
		//synchronized (lock) {
			String userId = commonBiz.checkValidatedUserId();
			masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
			if(!StringUtils.isBlank(userId)) {
				masterId = this.checkInspectMasterId(userId, masterId);
			}
		//}
		dto.setId(masterId);
		PageHelper.startPage(dto);
		List<BaseToolInfo> toolOverviews = checkMapper.getToolCheckOutList(dto);
		return PageUtils.toPageResult(toolOverviews);
	}

	@Override
	public PageResult<BaseToolInfo> getToolNeedCheckList(BaseDTO dto) {
		//Long masterId = checkMapper.getCheckMasterId();
		String masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
		String remindMasterId = checkMapper.getRemindMaterId();
		dto.setId(masterId);
		dto.setRemindMasterId(remindMasterId);
		PageHelper.startPage(dto);
		List<BaseToolInfo> toolOverviews = checkMapper.getToolNeedCheckList(dto);
		return PageUtils.toPageResult(toolOverviews);
	}

	@Override
	public List<BorrowPlanVO> getCheckToolInStatistical() {
		String masterId = null;
		String userId = null;
		//synchronized (lock) {
			userId = commonBiz.checkValidatedUserId();
			masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
			if(!StringUtils.isBlank(userId)) {
				masterId = this.checkInspectInMasterId(userId, masterId);
			}
		//}
		
		List<BorrowPlanVO> statistics = checkMapper.selectHasNoReturnToolByUserId(userId,masterId);
		return statistics;
	}
	/**
	 * 
	 * @description 检验入库的主表
	 * @param userId
	 * @param masterId
	 * @return
	 * @auther 韩兵
	 * @Date 2020年8月4日
	 * @return Long
	 */
	private String checkInspectInMasterId(String userId,String masterId) {
		ToolInspectInMaster master = null;
		if(StringUtils.isBlank(masterId)) {
			master = new ToolInspectInMaster();
			master.setCreateTime(new Date());
			master.setUserId(userId);
			master.setStatus(0);
			inspectInMasterMapper.insert(master);
			masterId = master.getId();
			CacheOperatorInfo.setMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), masterId);
			CacheOperatorInfo.setMapValue(CacheKeyName.BUSINESS_OPERATE_TYPE.getValue(), OperateType.INSPECT_IN_WAREHOUSE.getValue());
		}
		return masterId;
	}

	@Override
	public PageResult<BaseToolInfo> getCheckToolInList(BaseDTO dto) {
		String masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
		dto.setId(masterId);
		dto.setUserId(commonBiz.checkValidatedUserId());
		PageHelper.startPage(dto);
		List<BaseToolInfo> toolOverviews = checkMapper.getCheckToolInList(dto);
		
		if(null != toolOverviews && !toolOverviews.isEmpty()) {
	    	List<String> typeIds = toolOverviews.stream().map(BaseToolInfo::getTypeId).collect(Collectors.toList());
	    	List<DeviceSurplusTool> surpluses = commonMapper.selectDeviceSurplusTools(typeIds);
	    	toolOverviews.stream().forEach(vo->{
	    		for(DeviceSurplusTool surplus : surpluses) {
	    			if(vo.getTypeId().equals(surplus.getTypeId())) {
	    				vo.setBoxNum(surplus.getDeviceCode());
	    				break;
	    			}
	    		}
	    	});
	    }
		
		return PageUtils.toPageResult(toolOverviews);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void addException(ExceptionToolAddDTO dto) {
		if("0".equals(dto.getEum())){
			checkMapper.cacelException(dto);
		}else {
			dto.setUserId(EtmWebUtil.userId());
			checkMapper.addException(dto);
		}
	}

	@SuppressWarnings("rawtypes")
	@Override
	public ApiResult checkDoing() {
		CacheOperatorInfo.setMapValue(CacheKeyName.BUSINESS_OPERATE_TYPE.getValue(), OperateType.CHECK_WAREHOUSE.getValue());
		ToolCheckModel toolCheck = new ToolCheckModel();
		toolCheck.setCreateTime(new Date());
		toolCheck.setUserId(commonBiz.checkValidatedUserId());
		toolCheckRecordMapper.insert(toolCheck);
		//发送消息到主站
//		try {
//			List<CheckRecordSchema> records = new ArrayList<CheckRecordSchema>();
//			CheckRecordSchema record = new CheckRecordSchema();
//			record.setCreateDate(DateUtils.getDateStr(toolCheck.getCreateTime(), DateUtils.SDF_HH));
//			record.setOperateUserId(toolCheck.getUserId());
//			record.setOrgCode(masterConfig.getTerminalOrgCode());
//			records.add(record);
//			masterConfig.sendMsgToMaster(masterConfig.getMasterApiUrl()+masterConfig.getCheckRecordApi(), 
//					records, ApiResult.class);
//		}catch(Exception e) {
//			log.info("发送检查信息到主站异常：{}",e);
//		}
		return ApiResult.success();
	}

	@SuppressWarnings("rawtypes")
	@Override
	public ApiResult checkDone() {
		commonBiz.sendCommandToDevice(MqttSendCommandFunc.COMMAND_2002.getValue());
		commonBiz.sendCommandToDevice(MqttSendCommandFunc.COMMAND_2015.getValue());
		return commonBiz.confirmDeviceDoor();
	}

	@SuppressWarnings("rawtypes")
	@Override
	@Transactional
	public ApiResult outConfirmBorrow(String mechanismId,String inspectDate) {
		//处理业务
		ApiResult confirmDoor = commonBiz.confirmDeviceDoor();
		if(!confirmDoor.isSuccess()) {
			return confirmDoor;
		}
		
		String masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
		
		ToolInspectMaster master = inspectMasterMapper.selectById(masterId);
		if(null != master) {
			master.setStatus(1);
			master.setMechanismId(mechanismId);
			master.setInspectDate(DateUtils.getInstance().getDateByStr(inspectDate, DateUtils.getInstance().SDF_YM_DD2));
			inspectMasterMapper.updateById(master);
			
			@SuppressWarnings("unchecked")
			List<ToolInspectDetail> details = inspectDetailMapper.selectList(new Condition<ToolInspectDetail>().eq("master_id", masterId));
			
			if(null != details && !details.isEmpty()) {
				List<String> rfIds = details.stream().map(ToolInspectDetail::getToolId).collect(Collectors.toList());
				//更新工器具状态
				toolMapper.updateToolStatus(rfIds, 1, null);
				
				//发送更新的工器具状态
				//commonSendInfo.sendToolInfoByIds(rfIds);
//				String sendMechanismId = mechanismId;
//				MechanismModel m = mechanismMapper.selectById(mechanismId);
//				String sendMechanismName = m==null?"":m.getName();
//				String sendTestTime = inspectDate;
//				User user = userMapper.selectById(master.getUserId());
//				String useUser = user.getName();
//				commonSendInfo.sendToolInspectOut(master.getId(),rfIds, master.getUserId(),useUser,sendMechanismId, sendMechanismName, 
//						sendTestTime);
			}
		}
		CacheOperatorInfo.setMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
		CacheOperatorInfo.setMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null);
		//发送关闭柜子的命令
		commonBiz.lockDevice();
		return ApiResult.success();
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	@Transactional
	public ApiResult inConfirmBorrow(String checkDate) {
		if(StringUtils.isBlank(checkDate)) {
			return ApiResult.fail("请选择检验日期！");
		}
		//处理业务
		ApiResult confirmDoor = commonBiz.confirmDeviceDoor();
		if(!confirmDoor.isSuccess()) {
			return confirmDoor;
		}
		
		String masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
		
		ToolInspectInMaster master = inspectInMasterMapper.selectById(masterId);
		if(null != master) {
			master.setStatus(1);
			inspectInMasterMapper.updateById(master);
			List<ToolInspectInDetail> details = inspectInDetailMapper.selectList(new Condition<ToolInspectInDetail>().eq("master_id", masterId));
			Date inspectDate = StringUtils.isBlank(checkDate)?null:DateUtils.getInstance().getDateByStr(checkDate, DateUtils.getInstance().SDF_YM_DD2);
			//List<InspectRecordSchema> records = new ArrayList<InspectRecordSchema>();		
			if(null != details && !details.isEmpty()) {
				
				List<String> rfIds = details.stream().map(ToolInspectInDetail::getToolId).collect(Collectors.toList());
				List<Map<String,String>> toolInspectOutMasters = checkMapper.listLastInspectOutMasterId(rfIds);
				//更新检验时间
				details.stream().forEach(detail->{
					detail.setInspectTime(inspectDate);
					if(null != toolInspectOutMasters && !toolInspectOutMasters.isEmpty()) {
						toolInspectOutMasters.stream().forEach(map->{
							if(map.get("bookId").equals(detail.getToolId())) {
								detail.setExternalOutPkId(map.get("pkGqjcheckId"));
							}
						});
					}
					inspectInDetailMapper.updateById(detail);
//					try {
//						InspectRecordSchema record = new InspectRecordSchema();
//						ToolModel tool = toolMapper.selectById(detail.getToolId());
//						record.setEpc(tool.getCode());
//						record.setInspectDate(checkDate+" 00:00:00");
//						records.add(record);
//					}catch(Exception e) {
//						log.info("组装检验数据异常：{}",e);
//					}
				});
				
				checkMapper.updateInspectOutStatus(rfIds);
				//更新工器具状态
				toolMapper.updateToolStatusAndInspectDate(rfIds, 2);
				commonMapper.updateToolExceptionInWarehouseTime(rfIds);
				//发送更新的工器具状态
				//commonSendInfo.sendToolInfoByIds(rfIds);
				//发送检验数据到主站
//				commonSendInfo.sendToolInspectBack(toolInspectOutMasters,masterId);
////				if(!records.isEmpty()) {
////					masterConfig.sendMsgToMaster(masterConfig.getMasterApiUrl()+masterConfig.getInspectRecordApi(), 
////							records, ApiResult.class);
////				}
			}
		}
		
		CacheOperatorInfo.setMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
		CacheOperatorInfo.setMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null);
		//发送关闭柜子的命令
		commonBiz.lockDevice();
		return ApiResult.success();
	}
}
